package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.factory.StrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    //	cn.binarywang.wx.miniapp.api
    //	不需要spring 容器启动注入的实体bean 对象，需要对这个bean 对象重写！
    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private StrategyFactory strategyFactory;


    @Override
    public int updateUserVipStatus() {
        //  用户vip 到期了要更新is_vip=0;
        return userInfoMapper.updateUserVipStatus();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        //  记录用户购买的信息;
        ItemTypeStrategy itemTypeStrategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        itemTypeStrategy.savePaidRecord(userPaidRecordVo);
        //        if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
        //            //  购买专辑 user_paid_album
        //            UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)));
        //            //  判断对象是否为空：
        //            if (null != userPaidAlbum) {
        //                return;
        //            }
        //            //  购买专辑;
        //            userPaidAlbum = new UserPaidAlbum();
        //            //  赋值：
        //            userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
        //            userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
        //            userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
        //            //  保存记录;
        //            userPaidAlbumMapper.insert(userPaidAlbum);
        //        } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
        //            //  购买声音 user_paid_track
        //            //  10,11,12,13,14,15
        //            //  要购买的声音Id 列表；
        //            List<Long> itemIdList = userPaidRecordVo.getItemIdList();
        //            //  根据声音Id获取声音对象;
        //            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
        //            Assert.notNull(trackInfoResult, "查询声音信息失败！");
        //            TrackInfo trackInfo = trackInfoResult.getData();
        //            Assert.notNull(trackInfo, "查询声音信息失败！");
        //            //  查询用户已购买的声音Id;
        //            List<Long> userPaidTrackIdList = findUserPaidTrackList(trackInfo.getAlbumId(), userPaidRecordVo.getUserId());
        //            //  循环遍历;
        //            for (Long trackId : itemIdList) {
        //                //  判断！
        //                if (!CollectionUtils.isEmpty(userPaidTrackIdList)) {
        //                    //  获取相同的数据;发送消息退款;
        //                    if (userPaidTrackIdList.contains(trackId)) {
        //                        //  发送消息退款； 封装一个实体类; trackId; userId; amount; 调用wx支付api 或 增加账户余额;
        //                        //  rabbitService.sendDealyMessage(MqConst.EXCHANGE_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, trackId);
        //                    }
        //                }
        //                //  查询的是空！
        //                //  创建对象；
        //                UserPaidTrack userPaidTrack = new UserPaidTrack();
        //                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
        //                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
        //                userPaidTrack.setTrackId(trackId);
        //                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
        //                userPaidTrackMapper.insert(userPaidTrack);
        //            }
        //        } else {
        //            //  购买 vip user_vip_service ; vip续期
        //            UserVipService userVipService = new UserVipService();
        //            //  赋值：
        //            userVipService.setUserId(userPaidRecordVo.getUserId());
        //            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userVipService.setStartTime(new Date());
        //            //  过期时间;
        //            //  case 1: 用户第一次购买 user_info.is_vip=0； case 2: 用户续期；
        //            UserInfo userInfo = this.getById(userPaidRecordVo.getUserId());
        //            //  创建系统时间：
        //            Date currentTime = new Date();
        //            //  获取用户购买的时长;
        //            Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
        //            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
        //            Integer serviceMonth = vipServiceConfig.getServiceMonth();
        //            //  判断用户是否购买过vip;
        //            if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())) {
        //                //  续期;
        //                //  时长;serviceMonth
        //                currentTime = new LocalDateTime(userInfo.getVipExpireTime()).plusMonths(serviceMonth).toDate();
        //            } else {
        //                //  如果没有续期;
        //                currentTime = new LocalDateTime(currentTime).plusMonths(serviceMonth).toDate();
        //            }
        //            //  设置过期时间
        //            userVipService.setExpireTime(currentTime);
        //            //            //  购买vip 的时候出错!
        //            //            int i = 1 / 0;
        //            // 保存数据
        //            userVipServiceMapper.insert(userVipService);
        //            //  更新用户vip状态：
        //            userInfo.setIsVip(1);
        //            userInfo.setVipExpireTime(currentTime);
        //            this.updateById(userInfo);
        //        }
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //  select * from user_paid_track where user_id = 17 and album_id = 391;
        return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userId) {
        //  album_id and user_id
        return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
    }

    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, Long userId, List<Long> trackIdList) {
        //	先创建一个map 集合
        Map<Long, Integer> map = new HashMap<>();
        //	判断用户是否购买过专辑：user_paid_album
        //	select * from user_paid_album where user_id = ? and album_id = ?;
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        //	判断
        if (null != userPaidAlbum) {
            //	当前专辑下对应的所有声音Id 都应该免费!  map.put(trackId,1);
            return trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
        } else {
            //	当前这个用户没有购买过专辑; 购买过部分声音; 查询用户购买过当前专辑的声音Id 列表有哪些?
            LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).in(UserPaidTrack::getTrackId, trackIdList);
            //	购买过的声音Id 列表;
            List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
            List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            //	判断userPaidTrackList 是否为空;
            if (!CollectionUtils.isEmpty(userPaidTrackList)) {
                //	说明用户已经购买过部分声音; map.put(trackId,1);
                //  for (UserPaidTrack userPaidTrack : userPaidTrackList) {
                //      map.put(userPaidTrack.getTrackId(), 1);
                //  }
                for (Long trackId : trackIdList) {
                    //                    for (UserPaidTrack userPaidTrack : userPaidTrackList) {
                    //                        if (userPaidTrack.getTrackId() == trackId) {
                    //                            //  相等，购买过的;
                    //                            map.put(trackId, 1);
                    //                            //  如果相等，则跳出;
                    //                            break;
                    //                        } else {
                    //                            //  不相等; 未购买过!
                    //                            map.put(trackId, 0);
                    //                        }
                    //                    }
                    if (userPaidTrackIdList.contains(trackId)) {
                        System.out.println("用户购买过的声音Id" + trackId);
                        map.put(trackId, 1);
                    } else {
                        System.out.println("用户未购买过的声音Id" + trackId);
                        map.put(trackId, 0);
                    }
                }
            } else {
                //  用户没有购买过声音;
                for (Long trackId : trackIdList) {
                    map.put(trackId, 0);
                }
            }
        }
        //	返回数据
        return map;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo, Long userId) {
        //	更新数据
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝;
        userInfoVo.setId(userId);
        BeanUtils.copyProperties(userInfoVo, userInfo);
        this.updateById(userInfo);
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //	获取用户信息
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝;
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        //	返回数据
        return userInfoVo;
    }

    @Override
    public Map<String, Object> wxLogin(String code) {
        //	创建map集合
        Map<String, Object> map = new HashMap<>();
        //	code 与 微信相关的key 获取openid（每个微信用户对应的唯一标识）; 将这个微信标识存储到数据库表;如果表中有，则说明用户注册过。则登录成功，否则注册用户;并初始化一个账户金额
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //	获取用户的openid;
        String openid = wxMaJscode2SessionResult.getOpenid();
        //	根据openid 获取用户信息.
        //	select * from user_info where open_id = ?; 别写this.getOne();
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        //	判断用户对象是否为空
        if (null == userInfo) {
            //	用户未注册，则进行注册，并初始化账户金额;
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("听友:" + UUID.randomUUID().toString().substring(0, 6));
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //	保存数据
            this.save(userInfo);

            //	初始化账户金额; openFeignClient 发送消息的内容：userId
            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        //	声明一个token;
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //	将用户信息存储到缓存;
        String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        redisTemplate.opsForValue().set(loginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        //	存储数据;
        map.put("token", token);
        return map;
    }
}
